home *** CD-ROM | disk | FTP | other *** search
- // ------------------------------- //
- // -------- Start of File -------- //
- // ------------------------------- //
- // ----------------------------------------------------------- //
- // C++ Source Code File Name: rbtreeb.cpp
- // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
- // Produced By: Doug Gaer
- // File Creation Date: 01/23/1997
- // Date Last Modified: 03/15/1999
- // Copyright (c) 1997 Douglas M. Gaer
- // ----------------------------------------------------------- //
- // ------------- Program Description and Details ------------- //
- // ----------------------------------------------------------- //
- /*
- The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
- All those who put this code or its derivatives in a commercial
- product MUST mention this copyright in their documentation for
- users of the products in which this code or its derivative
- classes are used. Otherwise, you have the freedom to redistribute
- verbatim copies of this source code, adapt it to your specific
- needs, or improve the code and release your improvements to the
- public provided that the modified files carry prominent notices
- stating that you changed the files and the date of any change.
-
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
- THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
- IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
- YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
- CORRECTION.
-
- (R)ed (B)lack (T)ree node data independent functions.
- */
- // ----------------------------------------------------------- //
- #include "rbtreeb.h"
- #include "rbtree.h"
-
- // Convenience macros
- #define T (pp.t) // The current node
- #define P (pp.p) // Parent
- #define G (pp.g) // Grandparent
- #define GG (pp.gg) // Great Grandparent
- #define S (pp.s) // Sibling
- #define RS (pp.rs) // Right children of s
- #define LS (pp.ls) // Left children of s
- #define M (pp.m) // Matching node
- #define PM (pp.pm) // Parent of matching node
-
- RBNodeBase *InsBalance(RBNodeBase *Root, PtrPack &pp)
- // Balance adjusting for top down insertions. Eliminates
- // both P and T from being red by doing rotations and
- // color changes. G, P, and T assumed not null coming in.
- // GG may be null. At the end of this routine, only Tree
- // and P will be valid with each other. G and GG may
- // not reflect the proper ordering.
- {
- RBNodeBase *cofgg; // New child of great-grandparent
- int side;
-
- side = GG && GG->Right == G;
-
- if (G->Left == P) {
- if (P->Right == T) { // Do double rotate
- G->Left = T->Right;
- T->Right = G;
- P->Right = T->Left;
- T->Left = P;
- P = GG;
- cofgg = T;
- }
- else { // Do single rotate Right
- G->Left = P->Right;
- P->Right = G;
- cofgg = P;
- }
- }
- else { // G->Right == P
- if (P->Left == T) { // Do double rotate
- G->Right = T->Left;
- T->Left = G;
- P->Left = T->Right;
- T->Right = P;
- P = GG;
- cofgg = T;
- }
- else { // Do single rotate Left
- G->Right = P->Left;
- P->Left = G;
- cofgg = P;
- }
- }
-
- cofgg->color = BlackNode;
- G->color = RedNode;
-
- if (GG) {
- if (side) GG->Right = cofgg; else GG->Left = cofgg;
- }
- else Root = cofgg;
-
- return Root;
- }
-
- RBNodeBase *DelBalance(RBNodeBase *Root, PtrPack &pp)
- // Balancing code during top down deletion
- {
- if ((T == 0 || T->color == BlackNode) && S && S->color == RedNode) {
-
- // Case: T is black, S red. T might be null,
- // but S and P must not be.
-
- // Fix G child to be S. Also S may become P of M
- if (G) {
- if (G->Left == P) G->Left = S; else G->Right = S;
- }
- else Root = S;
- if (P == M) PM = S;
- // Finish rotating
- if (P->Left == T) {
- // RotateLeft(P);
- P->Right = LS;
- S->Left = P;
- G = S;
- S = LS;
- }
- else {
- // RotateRight(P);
- P->Left = RS;
- S->Right = P;
- G = S;
- S = RS;
- }
-
- // Fixup children of S
- if (S) { LS = S->GetLeft(); RS = S->GetRight(); }
- // Fixup colors
- P->color = RedNode; G->color = BlackNode;
- }
-
- if (T && T->color == BlackNode &&
- (T->Left == 0 || T->GetLeft()->color == BlackNode) &&
- (T->Right == 0 || T->GetRight()->color == BlackNode)) {
-
- // Case: T is a single binary node with two black children.
- if (S && S->color == BlackNode &&
- (S->Left == 0 || S->GetLeft()->color == BlackNode) &&
- (S->Right == 0 || S->GetRight()->color == BlackNode)) {
-
- // Case: T and S are single binary nodes with two black children..
- P->color = BlackNode; T->color = RedNode; S->color = RedNode;
-
- }
- else if (LS && LS->color == RedNode) {
-
- // Case: Tree is a single binary node with two black children.
- // S is pair of binary nodes-one red, one black or S is a set
- // of three binary nodes with a black parent and red child nodes.
- // LS is red or RS might be red.
-
- if (P->Left == T) {
- // Fix colors
- LS->color = P->color; P->color = BlackNode; T->color = RedNode;
- // Fix G child to be LS. ALSo LS may become P of M
- if (G) {
- if (G->Left == P) G->Left = LS; else G->Right = LS;
- }
- else Root = LS;
- if (P == M) PM = LS;
- // Finish: DoubleRotateLeft(S, P);
- P->Right = LS->Left;
- LS->Left = P;
- S->Left = LS->Right;
- LS->Right = S;
- G = LS;
- // Do not fix S or LS since they get reassigned
- // at the top of next loop
- }
- else {
- // Fix colors
- S->color = P->color; LS->color = BlackNode;
- P->color = BlackNode; T->color = RedNode;
- // Fix G child to be S. Also S may become P of M
- if (G) {
- if (G->Left == P) G->Left = S; else G->Right = S;
- }
- else Root = S;
- if (P == M) PM = S;
- // Finish: RotateRight(P);
- P->Left = RS;
- S->Right = P;
- G = S;
- // Do not fix S or LS since they get reassigned
- // at the top of next loop
- }
-
- }
- else if (RS && RS->color == RedNode) {
-
- // Case: T is a single binary node with two black children.
- // S is a pair of binary nodes-one red, one black.
- // LS is black, RS is red.
-
- if (P->Left == T) {
- // Fix colors
- RS->color = BlackNode; S->color = P->color;
- P->color = BlackNode; T->color = RedNode;
- // Fix G child to be S. Also, S may become P of M
- if (G) {
- if (G->Left == P) G->Left = S; else G->Right = S;
- }
- else Root = S;
- if (P == M) PM = S;
- // Finish: RotateLeft(P);
- P->Right = LS;
- S->Left = P;
- G = S;
- // Do not fix S or LS since they get reassigned
- // at the top of next loop
- }
- else {
- // Fix colors
- RS->color = P->color; P->color = BlackNode; T->color = RedNode;
- // Fix G child to become RS. ALSo, RS may become P of M.
- if (G) {
- if (G->Left == P) G->Left = RS; else G->Right = RS;
- }
- else Root = RS;
- if (P == M) PM = RS;
- // Finish: DoubleRotateRight(S, P);
- P->Left = RS->Right;
- RS->Right = P;
- S->Right = RS->Left;
- RS->Left = S;
- G = RS;
- // Do not fix S or LS since they get reassigned
- // at the top of next loop
- }
-
- }
- }
-
- return Root;
- }
-
- RBNodeBase *DoReplacement(RBNodeBase *Root, PtrPack &pp)
- // Swaps the node data in the matching node's successor with the
- // node data of the matching node to be deleted. Then the successor
- // node with no data is deleted. If the matching node has no successor
- // the parent node will equal the matching node and the replacement
- // node becomes the non-null child of the matching node.
- {
- // At this point, M is the node to delete, PM is it's parent,
- // P is the replacement node, G is it's parent. If M has no
- // successor, P will = M, and replacement is the non-null
- // child of M.
-
- if (M) { // Matching node was found
- if (P == M || M->Left == 0 || M->Right == 0) {
- // No successor, and/or at least one child null
- // Get non-null child, if any, else P will be null
- P = (M->Left) ? M->GetLeft() : M->GetRight();
- }
- else { // M has a successor to use as a replacement
- if (G != M) {
- // Successor is not immediate child of M, so detach
- // from where it is, attach to where M is
- G->Left = P->Right;
- P->Right = M->Right;
- }
- // Finish attaching where M is.
- P->Left = M->Left;
- }
- // P should have same color as M since it's going where M was
- if (P) P->color = M->color;
- }
-
- // Fixup PM child link to be P
- if (M) {
- if (PM) {
- if (PM->Left == M) PM->Left = P; else PM->Right = P;
- }
- else Root = P; // New Root, possibly null
- }
-
- return Root;
- }
-
- RBNodeBase *DetachMinMax(RBNodeBase *&Root, int mx)
- // Detach the smallest node in the tree (the node all the way to the left)
- // or the largest node in the tree (the node all the way to the right)
- // if mx is true.
- {
- struct PtrPack pp;
-
- if (Root == 0) return 0;
-
- T = Root; P = 0; G = 0;
- M = 0; PM = 0;
-
- while (T) {
-
- // Pretend we're on the matching node
- M = T; PM = P;
-
- // Update ancestor pointers
- G = P; P = T;
-
- // Then go all the way Left or Right
- if (mx) {
- T = P->GetRight(); S = P->GetLeft();
- }
- else {
- T = P->GetLeft(); S = P->GetRight();
- }
-
- if (S) {
- LS = S->GetLeft(); RS = S->GetRight();
- }
- else {
- LS = 0; RS = 0;
- }
-
- Root = DelBalance(Root, pp);
-
- } // end of while loop
-
- Root = DoReplacement(Root, pp);
-
- if (Root) Root->color = BlackNode;
-
- return M; // Node to delete
- }
- // ----------------------------------------------------------- //
- // ------------------------------- //
- // --------- End of File --------- //
- // ------------------------------- //
-